home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_kernel_source / FS / OPEN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-17  |  17.2 KB  |  849 lines

  1. /*
  2.  *  linux/fs/open.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. #include <linux/mm.h>
  8. #include <linux/utime.h>
  9. #include <linux/file.h>
  10. #include <linux/smp_lock.h>
  11. #include <linux/quotaops.h>
  12.  
  13. #include <asm/uaccess.h>
  14.  
  15. asmlinkage int sys_statfs(const char * path, struct statfs * buf)
  16. {
  17.     struct dentry * dentry;
  18.     int error;
  19.  
  20.     lock_kernel();
  21.     dentry = namei(path);
  22.     error = PTR_ERR(dentry);
  23.     if (!IS_ERR(dentry)) {
  24.         struct inode * inode = dentry->d_inode;
  25.         struct super_block * sb = inode->i_sb;
  26.  
  27.         error = -ENODEV;
  28.         if (sb && sb->s_op && sb->s_op->statfs)
  29.             error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
  30.  
  31.         dput(dentry);
  32.     }
  33.     unlock_kernel();
  34.     return error;
  35. }
  36.  
  37. asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
  38. {
  39.     struct file * file;
  40.     struct inode * inode;
  41.     struct dentry * dentry;
  42.     struct super_block * sb;
  43.     int error;
  44.  
  45.     lock_kernel();
  46.     error = -EBADF;
  47.     file = fget(fd);
  48.     if (!file)
  49.         goto out;
  50.     error = -ENOENT;
  51.     if (!(dentry = file->f_dentry))
  52.         goto out_putf;
  53.     if (!(inode = dentry->d_inode))
  54.         goto out_putf;
  55.     error = -ENODEV;
  56.     sb = inode->i_sb;
  57.     if (sb && sb->s_op && sb->s_op->statfs)
  58.         error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
  59. out_putf:
  60.     fput(file);
  61. out:
  62.     unlock_kernel();
  63.     return error;
  64. }
  65.  
  66. int do_truncate(struct dentry *dentry, unsigned long length)
  67. {
  68.     struct inode *inode = dentry->d_inode;
  69.     int error;
  70.     struct iattr newattrs;
  71.  
  72.     /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
  73.     if ((off_t) length < 0)
  74.         return -EINVAL;
  75.  
  76.     down(&inode->i_sem);
  77.     newattrs.ia_size = length;
  78.     newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
  79.     error = notify_change(dentry, &newattrs);
  80.     if (!error) {
  81.         /* truncate virtual mappings of this file */
  82.         vmtruncate(inode, length);
  83.         if (inode->i_op && inode->i_op->truncate)
  84.             inode->i_op->truncate(inode);
  85.     }
  86.     up(&inode->i_sem);
  87.     return error;
  88. }
  89.  
  90. asmlinkage int sys_truncate(const char * path, unsigned long length)
  91. {
  92.     struct dentry * dentry;
  93.     struct inode * inode;
  94.     int error;
  95.  
  96.     lock_kernel();
  97.     dentry = namei(path);
  98.  
  99.     error = PTR_ERR(dentry);
  100.     if (IS_ERR(dentry))
  101.         goto out;
  102.     inode = dentry->d_inode;
  103.  
  104.     error = -EACCES;
  105.     if (S_ISDIR(inode->i_mode))
  106.         goto dput_and_out;
  107.  
  108.     error = permission(inode,MAY_WRITE);
  109.     if (error)
  110.         goto dput_and_out;
  111.  
  112.     error = -EROFS;
  113.     if (IS_RDONLY(inode))
  114.         goto dput_and_out;
  115.  
  116.     error = -EPERM;
  117.     if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  118.         goto dput_and_out;
  119.  
  120.     error = get_write_access(inode);
  121.     if (error)
  122.         goto dput_and_out;
  123.  
  124.     error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
  125.                   length < inode->i_size ? length : inode->i_size,
  126.                   abs(inode->i_size - length));
  127.     if (!error) {
  128.         DQUOT_INIT(inode);
  129.         error = do_truncate(dentry, length);
  130.     }
  131.     put_write_access(inode);
  132. dput_and_out:
  133.     dput(dentry);
  134. out:
  135.     unlock_kernel();
  136.     return error;
  137. }
  138.  
  139. asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
  140. {
  141.     struct inode * inode;
  142.     struct dentry *dentry;
  143.     struct file * file;
  144.     int error;
  145.  
  146.     lock_kernel();
  147.     error = -EBADF;
  148.     file = fget(fd);
  149.     if (!file)
  150.         goto out;
  151.     error = -ENOENT;
  152.     if (!(dentry = file->f_dentry))
  153.         goto out_putf;
  154.     if (!(inode = dentry->d_inode))
  155.         goto out_putf;
  156.     error = -EACCES;
  157.     if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
  158.         goto out_putf;
  159.     error = -EPERM;
  160.     if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  161.         goto out_putf;
  162.     error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
  163.                   length<inode->i_size ? length : inode->i_size,
  164.                   abs(inode->i_size - length));
  165.     if (!error)
  166.         error = do_truncate(dentry, length);
  167. out_putf:
  168.     fput(file);
  169. out:
  170.     unlock_kernel();
  171.     return error;
  172. }
  173.  
  174. #ifndef __alpha__
  175.  
  176. /*
  177.  * sys_utime() can be implemented in user-level using sys_utimes().
  178.  * Is this for backwards compatibility?  If so, why not move it
  179.  * into the appropriate arch directory (for those architectures that
  180.  * need it).
  181.  */
  182.  
  183. /* If times==NULL, set access and modification to current time,
  184.  * must be owner or have write permission.
  185.  * Else, update from *times, must be owner or super user.
  186.  */
  187. asmlinkage int sys_utime(char * filename, struct utimbuf * times)
  188. {
  189.     int error;
  190.     struct dentry * dentry;
  191.     struct inode * inode;
  192.     struct iattr newattrs;
  193.  
  194.     lock_kernel();
  195.     dentry = namei(filename);
  196.  
  197.     error = PTR_ERR(dentry);
  198.     if (IS_ERR(dentry))
  199.         goto out;
  200.     inode = dentry->d_inode;
  201.  
  202.     error = -EROFS;
  203.     if (IS_RDONLY(inode))
  204.         goto dput_and_out;
  205.  
  206.     /* Don't worry, the checks are done in inode_change_ok() */
  207.     newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
  208.     if (times) {
  209.         error = get_user(newattrs.ia_atime, ×->actime);
  210.         if (!error) 
  211.             error = get_user(newattrs.ia_mtime, ×->modtime);
  212.         if (error)
  213.             goto dput_and_out;
  214.  
  215.         newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
  216.     } else {
  217.         if (current->fsuid != inode->i_uid &&
  218.             (error = permission(inode,MAY_WRITE)) != 0)
  219.             goto dput_and_out;
  220.     }
  221.     error = notify_change(dentry, &newattrs);
  222. dput_and_out:
  223.     dput(dentry);
  224. out:
  225.     unlock_kernel();
  226.     return error;
  227. }
  228.  
  229. #endif
  230.  
  231. /* If times==NULL, set access and modification to current time,
  232.  * must be owner or have write permission.
  233.  * Else, update from *times, must be owner or super user.
  234.  */
  235. asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
  236. {
  237.     int error;
  238.     struct dentry * dentry;
  239.     struct inode * inode;
  240.     struct iattr newattrs;
  241.  
  242.     lock_kernel();
  243.     dentry = namei(filename);
  244.  
  245.     error = PTR_ERR(dentry);
  246.     if (IS_ERR(dentry))
  247.         goto out;
  248.     inode = dentry->d_inode;
  249.  
  250.     error = -EROFS;
  251.     if (IS_RDONLY(inode))
  252.         goto dput_and_out;
  253.  
  254.     /* Don't worry, the checks are done in inode_change_ok() */
  255.     newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
  256.     if (utimes) {
  257.         struct timeval times[2];
  258.         error = -EFAULT;
  259.         if (copy_from_user(×, utimes, sizeof(times)))
  260.             goto dput_and_out;
  261.         newattrs.ia_atime = times[0].tv_sec;
  262.         newattrs.ia_mtime = times[1].tv_sec;
  263.         newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
  264.     } else {
  265.         if ((error = permission(inode,MAY_WRITE)) != 0)
  266.             goto dput_and_out;
  267.     }
  268.     error = notify_change(dentry, &newattrs);
  269. dput_and_out:
  270.     dput(dentry);
  271. out:
  272.     unlock_kernel();
  273.     return error;
  274. }
  275.  
  276. /*
  277.  * access() needs to use the real uid/gid, not the effective uid/gid.
  278.  * We do this by temporarily clearing all FS-related capabilities and
  279.  * switching the fsuid/fsgid around to the real ones.
  280.  */
  281. asmlinkage int sys_access(const char * filename, int mode)
  282. {
  283.     struct dentry * dentry;
  284.     int old_fsuid, old_fsgid;
  285.     kernel_cap_t old_cap;
  286.     int res = -EINVAL;
  287.  
  288.     lock_kernel();
  289.     if (mode != (mode & S_IRWXO))    /* where's F_OK, X_OK, W_OK, R_OK? */
  290.         goto out;
  291.     old_fsuid = current->fsuid;
  292.     old_fsgid = current->fsgid;
  293.     old_cap = current->cap_effective;
  294.  
  295.     current->fsuid = current->uid;
  296.     current->fsgid = current->gid;
  297.  
  298.     /* Clear the capabilities if we switch to a non-root user */
  299.     if (current->uid)
  300.         cap_clear(current->cap_effective);
  301.     else
  302.         current->cap_effective = current->cap_permitted;
  303.         
  304.     dentry = namei(filename);
  305.     res = PTR_ERR(dentry);
  306.     if (!IS_ERR(dentry)) {
  307.         res = permission(dentry->d_inode, mode);
  308.         /* SuS v2 requires we report a read only fs too */
  309.         if(!res && (mode & S_IWOTH) && IS_RDONLY(dentry->d_inode))
  310.             res = -EROFS;
  311.         dput(dentry);
  312.     }
  313.  
  314.     current->fsuid = old_fsuid;
  315.     current->fsgid = old_fsgid;
  316.     current->cap_effective = old_cap;
  317. out:
  318.     unlock_kernel();
  319.     return res;
  320. }
  321.  
  322. asmlinkage int sys_chdir(const char * filename)
  323. {
  324.     int error;
  325.     struct inode *inode;
  326.     struct dentry *dentry, *tmp;
  327.  
  328.     lock_kernel();
  329.     
  330.     dentry = namei(filename);
  331.     error = PTR_ERR(dentry);
  332.     if (IS_ERR(dentry))
  333.         goto out;
  334.  
  335.     inode = dentry->d_inode;
  336.  
  337.     error = -ENOTDIR;
  338.     if (!S_ISDIR(inode->i_mode))
  339.         goto dput_and_out;
  340.  
  341.     error = permission(inode,MAY_EXEC);
  342.     if (error)
  343.         goto dput_and_out;
  344.  
  345.     /* exchange dentries */
  346.     tmp = current->fs->pwd;
  347.     current->fs->pwd = dentry;
  348.     dentry = tmp;
  349.  
  350. dput_and_out:
  351.     dput(dentry);
  352. out:
  353.     unlock_kernel();
  354.     return error;
  355. }
  356.  
  357. asmlinkage int sys_fchdir(unsigned int fd)
  358. {
  359.     struct file *file;
  360.     struct dentry *dentry;
  361.     struct inode *inode;
  362.     int error;
  363.  
  364.     lock_kernel();
  365.  
  366.     error = -EBADF;
  367.     file = fget(fd);
  368.     if (!file)
  369.         goto out;
  370.  
  371.     error = -ENOENT;
  372.     if (!(dentry = file->f_dentry))
  373.         goto out_putf;
  374.     if (!(inode = dentry->d_inode))
  375.         goto out_putf;
  376.  
  377.     error = -ENOTDIR;
  378.     if (!S_ISDIR(inode->i_mode))
  379.         goto out_putf;
  380.  
  381.     error = permission(inode, MAY_EXEC);
  382.     if (!error) {
  383.         struct dentry *tmp = current->fs->pwd;
  384.         current->fs->pwd = dget(dentry);
  385.         dput(tmp);
  386.     }
  387. out_putf:
  388.     fput(file);
  389. out:
  390.     unlock_kernel();
  391.     return error;
  392. }
  393.  
  394. asmlinkage int sys_chroot(const char * filename)
  395. {
  396.     int error;
  397.     struct inode *inode;
  398.     struct dentry *dentry, *tmp;
  399.  
  400.     lock_kernel();
  401.     
  402.     dentry = namei(filename);
  403.     error = PTR_ERR(dentry);
  404.     if (IS_ERR(dentry))
  405.         goto out;
  406.  
  407.     inode = dentry->d_inode;
  408.  
  409.     error = -ENOTDIR;
  410.     if (!S_ISDIR(inode->i_mode))
  411.         goto dput_and_out;
  412.  
  413.     error = permission(inode,MAY_EXEC);
  414.     if (error)
  415.         goto dput_and_out;
  416.  
  417.     error = -EPERM;
  418.     if (!capable(CAP_SYS_CHROOT))
  419.         goto dput_and_out;
  420.  
  421.     /* exchange dentries */
  422.     tmp = current->fs->root;
  423.     current->fs->root = dentry;
  424.     dentry = tmp;
  425.     error = 0;
  426.  
  427. dput_and_out:
  428.     dput(dentry);
  429. out:
  430.     unlock_kernel();
  431.     return error;
  432. }
  433.  
  434. asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
  435. {
  436.     struct inode * inode;
  437.     struct dentry * dentry;
  438.     struct file * file;
  439.     int err = -EBADF;
  440.     struct iattr newattrs;
  441.  
  442.     lock_kernel();
  443.     file = fget(fd);
  444.     if (!file)
  445.         goto out;
  446.  
  447.     err = -ENOENT;
  448.     if (!(dentry = file->f_dentry))
  449.         goto out_putf;
  450.     if (!(inode = dentry->d_inode))
  451.         goto out_putf;
  452.  
  453.     err = -EROFS;
  454.     if (IS_RDONLY(inode))
  455.         goto out_putf;
  456.     err = -EPERM;
  457.     if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  458.         goto out_putf;
  459.     if (mode == (mode_t) -1)
  460.         mode = inode->i_mode;
  461.     newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  462.     newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
  463.     err = notify_change(dentry, &newattrs);
  464.  
  465. out_putf:
  466.     fput(file);
  467. out:
  468.     unlock_kernel();
  469.     return err;
  470. }
  471.  
  472. asmlinkage int sys_chmod(const char * filename, mode_t mode)
  473. {
  474.     struct dentry * dentry;
  475.     struct inode * inode;
  476.     int error;
  477.     struct iattr newattrs;
  478.  
  479.     lock_kernel();
  480.     dentry = namei(filename);
  481.  
  482.     error = PTR_ERR(dentry);
  483.     if (IS_ERR(dentry))
  484.         goto out;
  485.     inode = dentry->d_inode;
  486.  
  487.     error = -EROFS;
  488.     if (IS_RDONLY(inode))
  489.         goto dput_and_out;
  490.  
  491.     error = -EPERM;
  492.     if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  493.         goto dput_and_out;
  494.  
  495.     if (mode == (mode_t) -1)
  496.         mode = inode->i_mode;
  497.     newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  498.     newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
  499.     error = notify_change(dentry, &newattrs);
  500.  
  501. dput_and_out:
  502.     dput(dentry);
  503. out:
  504.     unlock_kernel();
  505.     return error;
  506. }
  507.  
  508. static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
  509. {
  510.     struct inode * inode;
  511.     int error;
  512.     struct iattr newattrs;
  513.  
  514.     error = -ENOENT;
  515.     if (!(inode = dentry->d_inode)) {
  516.         printk("chown_common: NULL inode\n");
  517.         goto out;
  518.     }
  519.     error = -EROFS;
  520.     if (IS_RDONLY(inode))
  521.         goto out;
  522.     error = -EPERM;
  523.     if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  524.         goto out;
  525.     if (user == (uid_t) -1)
  526.         user = inode->i_uid;
  527.     if (group == (gid_t) -1)
  528.         group = inode->i_gid;
  529.     newattrs.ia_mode = inode->i_mode;
  530.     newattrs.ia_uid = user;
  531.     newattrs.ia_gid = group;
  532.     newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
  533.     /*
  534.      * If the user or group of a non-directory has been changed by a
  535.      * non-root user, remove the setuid bit.
  536.      * 19981026    David C Niemi <niemi@tux.org>
  537.      *
  538.      */
  539.     if ((inode->i_mode & S_ISUID) == S_ISUID &&
  540.         !S_ISDIR(inode->i_mode)
  541.         && current->fsuid) 
  542.     {
  543.         newattrs.ia_mode &= ~S_ISUID;
  544.         newattrs.ia_valid |= ATTR_MODE;
  545.     }
  546.     /*
  547.      * Likewise, if the user or group of a non-directory has been changed
  548.      * by a non-root user, remove the setgid bit UNLESS there is no group
  549.      * execute bit (this would be a file marked for mandatory locking).
  550.      * 19981026    David C Niemi <niemi@tux.org>
  551.      */
  552.     if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) 
  553.         && !S_ISDIR(inode->i_mode) && current->fsuid) 
  554.     {
  555.         newattrs.ia_mode &= ~S_ISGID;
  556.         newattrs.ia_valid |= ATTR_MODE;
  557.     }
  558.     error = DQUOT_TRANSFER(dentry, &newattrs);
  559. out:
  560.     return error;
  561. }
  562.  
  563. asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
  564. {
  565.     struct dentry * dentry;
  566.     int error;
  567.  
  568.     lock_kernel();
  569.     dentry = namei(filename);
  570.  
  571.     error = PTR_ERR(dentry);
  572.     if (!IS_ERR(dentry)) {
  573.         error = chown_common(dentry, user, group);
  574.         dput(dentry);
  575.     }
  576.     unlock_kernel();
  577.     return error;
  578. }
  579.  
  580. asmlinkage int sys_lchown(const char * filename, uid_t user, gid_t group)
  581. {
  582.     struct dentry * dentry;
  583.     int error;
  584.  
  585.     lock_kernel();
  586.     dentry = lnamei(filename);
  587.  
  588.     error = PTR_ERR(dentry);
  589.     if (!IS_ERR(dentry)) {
  590.         error = chown_common(dentry, user, group);
  591.         dput(dentry);
  592.     }
  593.     unlock_kernel();
  594.     return error;
  595. }
  596.  
  597.  
  598. asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
  599. {
  600.     struct dentry * dentry;
  601.     struct file * file;
  602.     int error = -EBADF;
  603.  
  604.     lock_kernel();
  605.     file = fget(fd);
  606.     if (!file)
  607.         goto out;
  608.     error = -ENOENT;
  609.     if ((dentry = file->f_dentry) != NULL)
  610.         error = chown_common(dentry, user, group);
  611.     fput(file);
  612.  
  613. out:
  614.     unlock_kernel();
  615.     return error;
  616. }
  617.  
  618. /*
  619.  * Note that while the flag value (low two bits) for sys_open means:
  620.  *    00 - read-only
  621.  *    01 - write-only
  622.  *    10 - read-write
  623.  *    11 - special
  624.  * it is changed into
  625.  *    00 - no permissions needed
  626.  *    01 - read-permission
  627.  *    10 - write-permission
  628.  *    11 - read-write
  629.  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  630.  * used by symlinks.
  631.  */
  632. struct file *filp_open(const char * filename, int flags, int mode)
  633. {
  634.     struct inode * inode;
  635.     struct dentry * dentry;
  636.     struct file * f;
  637.     int flag,error;
  638.  
  639.     error = -ENFILE;
  640.     f = get_empty_filp();
  641.     if (!f)
  642.         goto out;
  643.     f->f_flags = flag = flags;
  644.     f->f_mode = (flag+1) & O_ACCMODE;
  645.     if (f->f_mode)
  646.         flag++;
  647.     if (flag & O_TRUNC)
  648.         flag |= 2;
  649.     dentry = open_namei(filename,flag,mode);
  650.     error = PTR_ERR(dentry);
  651.     if (IS_ERR(dentry))
  652.         goto cleanup_file;
  653.     inode = dentry->d_inode;
  654.     if (f->f_mode & FMODE_WRITE) {
  655.         error = get_write_access(inode);
  656.         if (error)
  657.             goto cleanup_dentry;
  658.     }
  659.  
  660.     f->f_dentry = dentry;
  661.     f->f_pos = 0;
  662.     f->f_reada = 0;
  663.     f->f_op = NULL;
  664.     if (inode->i_op)
  665.         f->f_op = inode->i_op->default_file_ops;
  666.     if (f->f_op && f->f_op->open) {
  667.         error = f->f_op->open(inode,f);
  668.         if (error)
  669.             goto cleanup_all;
  670.     }
  671.     f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
  672.  
  673.     return f;
  674.  
  675. cleanup_all:
  676.     if (f->f_mode & FMODE_WRITE)
  677.         put_write_access(inode);
  678. cleanup_dentry:
  679.     f->f_dentry = NULL;
  680.     dput(dentry);
  681. cleanup_file:
  682.     put_filp(f);
  683. out:
  684.     return ERR_PTR(error);
  685. }
  686.  
  687. /*
  688.  * Find an empty file descriptor entry, and mark it busy.
  689.  */
  690. int get_unused_fd(void)
  691. {
  692.     struct files_struct * files = current->files;
  693.     int fd, error;
  694.  
  695.     error = -EMFILE;
  696.     fd = find_first_zero_bit(&files->open_fds, NR_OPEN);
  697.     /*
  698.      * N.B. For clone tasks sharing a files structure, this test
  699.      * will limit the total number of files that can be opened.
  700.      */
  701.     if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
  702.         goto out;
  703.  
  704.     /* Check here for fd > files->max_fds to do dynamic expansion */
  705.  
  706.     FD_SET(fd, &files->open_fds);
  707.     FD_CLR(fd, &files->close_on_exec);
  708. #if 1
  709.     /* Sanity check */
  710.     if (files->fd[fd] != NULL) {
  711.         printk("get_unused_fd: slot %d not NULL!\n", fd);
  712.         files->fd[fd] = NULL;
  713.     }
  714. #endif
  715.     error = fd;
  716.  
  717. out:
  718.     return error;
  719. }
  720.  
  721. inline void put_unused_fd(unsigned int fd)
  722. {
  723.     FD_CLR(fd, ¤t->files->open_fds);
  724. }
  725.  
  726. asmlinkage int sys_open(const char * filename, int flags, int mode)
  727. {
  728.     char * tmp;
  729.     int fd, error;
  730.  
  731.     tmp = getname(filename);
  732.     fd = PTR_ERR(tmp);
  733.     if (!IS_ERR(tmp)) {
  734.         lock_kernel();
  735.         fd = get_unused_fd();
  736.         if (fd >= 0) {
  737.             struct file * f = filp_open(tmp, flags, mode);
  738.             error = PTR_ERR(f);
  739.             if (IS_ERR(f))
  740.                 goto out_error;
  741.             fd_install(fd, f);
  742.         }
  743. out:
  744.         unlock_kernel();
  745.         putname(tmp);
  746.     }
  747.     return fd;
  748.  
  749. out_error:
  750.     put_unused_fd(fd);
  751.     fd = error;
  752.     goto out;
  753. }
  754.  
  755. #ifndef __alpha__
  756.  
  757. /*
  758.  * For backward compatibility?  Maybe this should be moved
  759.  * into arch/i386 instead?
  760.  */
  761. asmlinkage int sys_creat(const char * pathname, int mode)
  762. {
  763.     return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
  764. }
  765.  
  766. #endif
  767.  
  768. /*
  769.  * Called when retiring the last use of a file pointer.
  770.  */
  771. void __fput(struct file *filp)
  772. {
  773.     struct dentry * dentry = filp->f_dentry;
  774.     struct inode * inode = dentry->d_inode;
  775.  
  776.     if (filp->f_op && filp->f_op->release)
  777.         filp->f_op->release(inode, filp);
  778.     filp->f_dentry = NULL;
  779.     if (filp->f_mode & FMODE_WRITE)
  780.         put_write_access(inode);
  781.     dput(dentry);
  782. }
  783.  
  784. /*
  785.  * "id" is the POSIX thread ID. We use the
  786.  * files pointer for this..
  787.  */
  788. int filp_close(struct file *filp, fl_owner_t id)
  789. {
  790.     int retval;
  791.     struct dentry *dentry = filp->f_dentry;
  792.  
  793.     if (filp->f_count == 0) {
  794.         printk("VFS: Close: file count is 0\n");
  795.         return 0;
  796.     }
  797.     retval = 0;
  798.     if (filp->f_op && filp->f_op->flush)
  799.         retval = filp->f_op->flush(filp);
  800.     if (dentry->d_inode)
  801.         locks_remove_posix(filp, id);
  802.     fput(filp);
  803.     return retval;
  804. }
  805.  
  806. /*
  807.  * Careful here! We test whether the file pointer is NULL before
  808.  * releasing the fd. This ensures that one clone task can't release
  809.  * an fd while another clone is opening it.
  810.  */
  811. asmlinkage int sys_close(unsigned int fd)
  812. {
  813.     int error;
  814.     struct file * filp;
  815.  
  816.     lock_kernel();
  817.     error = -EBADF;
  818.     filp = fcheck(fd);
  819.     if (filp) {
  820.         struct files_struct * files = current->files;
  821.         files->fd[fd] = NULL;
  822.         put_unused_fd(fd);
  823.         FD_CLR(fd, &files->close_on_exec);
  824.         error = filp_close(filp, files);
  825.     }
  826.     unlock_kernel();
  827.     return error;
  828. }
  829.  
  830. /*
  831.  * This routine simulates a hangup on the tty, to arrange that users
  832.  * are given clean terminals at login time.
  833.  */
  834. asmlinkage int sys_vhangup(void)
  835. {
  836.     int ret = -EPERM;
  837.  
  838.     lock_kernel();
  839.     if (!capable(CAP_SYS_TTY_CONFIG))
  840.         goto out;
  841.     /* If there is a controlling tty, hang it up */
  842.     if (current->tty)
  843.         tty_vhangup(current->tty);
  844.     ret = 0;
  845. out:
  846.     unlock_kernel();
  847.     return ret;
  848. }
  849.